﻿using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Windows;
using Language.Utility;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;

namespace Language.Intellisense.NavigationBar
{
    class Margin : IWpfTextViewMargin
    {
        #region Private Data

        private Control _control = new Control();
        private Stub.Database _database;
        private string _filepath;

        #endregion Private Data

        #region C-Tor

        public Margin( Stub.Database database, IWpfTextViewHost wpfTextViewHost )
        {
            _database = database;

            string absolutePath = wpfTextViewHost.TextView.TextBuffer.ExtractFilename();

            Utility.FilePath processedPath = new Utility.FilePath() { Absolute = absolutePath };
            _filepath = processedPath.Relative;

            database.Updated += Database_Updated;
            wpfTextViewHost.TextView.Caret.PositionChanged += Caret_PositionChanged;

            Stub.File file;
            if ( _database.FileByPath.TryGetValue( _filepath, out file ) )
            {
                _control.File = file;
            }
        }

        #endregion C-Tor

        #region Private Methods

        private void Caret_PositionChanged( object sender, CaretPositionChangedEventArgs e )
        {
            _control.Position = e.NewPosition.BufferPosition.Position;
        }

        private void Database_Updated( object sender, Stub.Database.SnapshotUpdatedArgs e )
        {
            if ( e.File == _filepath )
            {
                _control.File = _database.FileByPath[ _filepath ];
            }
        }

        #endregion Private Methods

        #region IWpfTextViewMargin

        bool ITextViewMargin.Enabled => true;
        double ITextViewMargin.MarginSize => _control.ActualHeight;
        FrameworkElement IWpfTextViewMargin.VisualElement => _control;

        ITextViewMargin ITextViewMargin.GetTextViewMargin( string marginName )
        {
            Debug.Print( $"Searched for margins: {marginName}" );
            return null;
        }

        #endregion IWpfTextViewMargin

        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose( bool disposing )
        {
            if ( !disposedValue )
            {
                if ( disposing )
                {
                    // TODO: dispose managed state (managed objects).
                }

                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.

                disposedValue = true;
            }
        }

        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
        // ~Margin() {
        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        //   Dispose(false);
        // }

        // This code added to correctly implement the disposable pattern.
        void IDisposable.Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose( true );
            // TODO: uncomment the following line if the finalizer is overridden above.
            // GC.SuppressFinalize(this);
        }
        #endregion

    }

    #region Provider

    [Export( typeof( IWpfTextViewMarginProvider ) )]
    [Name( "Red Scripts Navigation Bar" )]
    [Order( Before = "Wpf Line Number Margin" )]
    [MarginContainer( PredefinedMarginNames.Top )]
    [ContentType( "redscript" )]
    [TextViewRole( PredefinedTextViewRoles.Document )]
    class MarginProvider : IWpfTextViewMarginProvider
    {
        #region Imports

        [Import]
        public Stub.Database Database { get; set; }

        [Import]
        private Settings _settings = null;

        #endregion Imports

        #region IWpfTextViewMarginProvider

        IWpfTextViewMargin IWpfTextViewMarginProvider.CreateMargin( IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin marginContainer )
        {
            _settings.Refresh();

            if( _settings.IsTheNavigationBarEnabled )
                return wpfTextViewHost.TextView.Properties.GetOrCreateSingletonProperty( () => new Margin( Database, wpfTextViewHost ) );

            return null;
        }

        #endregion IWpfTextViewMarginProvider
    }

    #endregion Provider
}
